package com.fin.zw.aiqas.service;

import com.fin.zw.aiqas.entity.*;
import com.fin.zw.aiqas.model.request.RuleInfoRequest;
import com.fin.zw.aiqas.model.request.RuleTableRequest;
import com.fin.zw.aiqas.model.response.FormulaResponse;
import com.fin.zw.aiqas.model.response.RuleInfoResponse;
import com.fin.zw.aiqas.model.response.RuleInfoTableResponse;
import com.fin.zw.aiqas.model.session.SessionModel;
import com.fin.zw.aiqas.repository.*;
import com.fin.zw.aiqas.util.BadRequestException;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections.IteratorUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service(value = "inspectionRuleService")
public class RuleInspectionService {

    private final static Logger log = LoggerFactory.getLogger(RuleInspectionService.class);

    @Autowired
    private RuleInfoRepository ruleInfoRepository;


    @Autowired
    private FormulaInfoRepository formulaInfoRepository;

    @Autowired
    private KeywordRepository keywordRepository;

    @Autowired
    private RuleTypeRepository ruleTypeRepository;
    @Autowired
    private ScenesRepository scenesRepository;

    @Autowired
    private ConverseRuleRepository converseRuleRepository;

    @Autowired
    private TaskInfoRepository taskInfoRepository;

    /**
     * 添加规则信息
     */
    public void addRuleInfo(RuleInfoRequest request, SessionModel session) {
        log.info("开始执行添加质检规则操作....");
        Iterable<RuleInfo> all = ruleInfoRepository.findAll(QRuleInfo.ruleInfo.ruleCode.eq(request.getRuleCode()));
        if (all.iterator().hasNext()) {
            throw new BadRequestException("", "不能出现相同编码的规则！！！！");
        }
        RuleInfo rule = new RuleInfo();
        BeanUtils.copyProperties(request, rule);
        rule.setOperatorId(session.getUserId());
        rule.setOperatorRealName(session.getUserName());
        rule.setCreateTime(new Date());
        Set<FormulaInfo> keywords = new HashSet<>();
        request.getFormulaIds().forEach(e -> keywords.add(formulaInfoRepository.getOne(e)));
        rule.setFormulaInfos(keywords);
        ScenesInfo scenesInfo = scenesRepository.findById(request.getScenesId()).orElseThrow(() -> new BadRequestException("", "样本场景异常!!"));
        rule.setScenesInfo(scenesInfo);
        rule.setRuleLevel(request.getRuleLevel());
        rule.setRuleCode(request.getRuleCode());
        ruleInfoRepository.save(rule);
        log.info("添加质检规则添加完成！");
    }

    /**
     * 修改规则信息
     */
    public void updateRuleById(RuleInfoRequest request, SessionModel session) throws RuntimeException {
        log.info("开始执行修改质检规则操作....");
        BooleanBuilder builder = new BooleanBuilder();
        QRuleInfo qRuleInfo = QRuleInfo.ruleInfo;
        builder.and(qRuleInfo.ruleCode.eq(request.getRuleCode()));
        builder.and(qRuleInfo.id.notIn(request.getId()));
        Iterable<RuleInfo> all = ruleInfoRepository.findAll(builder);
        if (all.iterator().hasNext()) {
            throw new BadRequestException("", "不能出现相同编码的规则！！！！");
        }
        Optional<RuleInfo> optional = ruleInfoRepository.findById(request.getId());
        if (!optional.isPresent()) {
            throw new BadRequestException("", "规则信息不存在！");
        }
        RuleInfo rule = optional.get();
        BeanUtils.copyProperties(request, rule);
        rule.setUpdateTime(new Date());
        rule.setUpdateRealName(session.getUserName());
        rule.setUpdateUserId(session.getUserId());
        Set<FormulaInfo> keywords = new HashSet<>();
        request.getFormulaIds().forEach(e -> keywords.add(formulaInfoRepository.getOne(e)));
        ScenesInfo scenesInfo = scenesRepository.findById(request.getScenesId()).orElseThrow(() -> new BadRequestException("", "样本场景异常!!"));
        rule.setScenesInfo(scenesInfo);
        rule.setFormulaInfos(keywords);
        ruleInfoRepository.save(rule);
        log.info("质检规则修改完成！");
    }


    /**
     * 删除规则信息级联删除质检点信息
     */
    @Transactional
    public void deleteRuleById(Long ruleId) {
        if (ruleId != null) {
            Optional<RuleInfo> optional = ruleInfoRepository.findById(ruleId);
            if (!optional.isPresent()) {
                throw new BadRequestException("", "需要删除的规则信息不存在！");
            }
            RuleInfo ruleInfo = optional.get();
            Iterator<TaskInfo> iterator = taskInfoRepository.findAll(QTaskInfo.taskInfo.ruleInfoSet.contains(ruleInfo)).iterator();
            if (iterator.hasNext()) {
                throw new BadRequestException("", "该规则在任务中使用吗，不允许删除");
            }
            Iterator<ConverseRule> ruleIterator = converseRuleRepository.findAll(QConverseRule.converseRule.ruleInfo.id.eq(ruleId)).iterator();
            if (ruleIterator.hasNext()) {
                throw new BadRequestException("", "该规则已经被质检出，不允许删除！");
            }
            ruleInfoRepository.delete(ruleInfo);
        } else {
            throw new BadRequestException("", "删除ID时规则ID不能为空!");
        }
    }

    /**
     * 查询规则列表信息
     */
    @Transactional
    public Page<RuleInfoTableResponse> queryRuleTable(RuleTableRequest request, Pageable pageable) {
        BooleanBuilder builder = new BooleanBuilder();
        QRuleInfo qRuleInfo = QRuleInfo.ruleInfo;
        if (StringUtils.isNotEmpty(request.getRuleName())) {
            builder.and(qRuleInfo.ruleName.like("%" + request.getRuleName() + "%"));
        }
        if (request.getStartTime() != null && request.getEndTime() != null) {
            builder.and(qRuleInfo.createTime.between(request.getStartTime(), request.getEndTime()));
        }
        if (request.getScenesInfoId()!=null) {
            builder.and(qRuleInfo.scenesInfo.id.eq(request.getScenesInfoId()));
        }
        if (StringUtils.isNotBlank(request.getRuleLevel())) {
            builder.and(qRuleInfo.ruleLevel.like("%".concat(request.getRuleLevel()).concat("%")));
        }
        if (StringUtils.isNotBlank(request.getRuleCode())) {
            builder.and(qRuleInfo.ruleCode.like("%".concat(request.getRuleCode()).concat("%")));
        }
        log.info("将关联的规则分类ID转化为汉字在列表中显示");
        Page<RuleInfo> pageAble = ruleInfoRepository.findAll(builder, pageable);
        List<RuleType> ruleTypeList = IteratorUtils.toList(ruleTypeRepository.findAll().iterator());
        Map<Long, String> ruleTypeMap = new HashMap<>();
        ruleTypeList.forEach(ruleType -> {
            ruleTypeMap.put(ruleType.getId(), ruleType.getName());
        });
        Page<RuleInfoTableResponse> page = pageAble.map(ruleInfo -> {
            RuleInfoTableResponse response = new RuleInfoTableResponse();
            BeanUtils.copyProperties(ruleInfo, response);
            List<Long> list = new ArrayList();
            response.setRuleTypeName(ruleTypeMap.get(ruleInfo.getRuleTypeId()));
            ruleInfo.getFormulaInfos().forEach(e -> {
                list.add(e.getId());
            });
            response.setFormulaIds(list);
            return response;
        });
        return page;
    }

    /**
     * 根据id查询规则信息
     */
    public RuleInfoResponse queryRuleById(Long id) {
        log.info("查询规则表信息.....");
        RuleInfo ruleInfo = ruleInfoRepository.findById(id).orElseThrow(() -> new BadRequestException("", "查询的规则信息不存在！！"));
        RuleInfoResponse response = new RuleInfoResponse();
        BeanUtils.copyProperties(ruleInfo, response);
        List<FormulaResponse> list = new ArrayList();
        response.setFormulaResponses(list);
        ruleInfo.getFormulaInfos().forEach(e -> {
            ArrayList<Keyword> keywords = Lists.newArrayList(keywordRepository.findAll(new BooleanBuilder().and(QKeyword.keyword.keyword_info_id.eq(e.getId()))));
            Set<String> keywordSet = new HashSet<>();
            keywords.stream().forEach(t -> {
                keywordSet.add(t.getName());
            });
            FormulaResponse formulaResponse = new FormulaResponse();
            BeanUtils.copyProperties(e, formulaResponse);
            formulaResponse.setKeywords(keywordSet);
            list.add(formulaResponse);
        });
        return response;
    }


    /**
     * 查询质检规则全部信息
     *
     * @return
     */
    public List<RuleInfoTableResponse> fetchRuleInfo(RuleTableRequest request) {
        QRuleInfo qruleInfo = QRuleInfo.ruleInfo;
        BooleanBuilder builder = new BooleanBuilder();
        if (request.getScenesInfoId() != null) builder.and(qruleInfo.scenesInfo.id.eq(request.getScenesInfoId()));
        if (StringUtils.isNotBlank(request.getRuleName())) builder.and(qruleInfo.ruleName.eq(request.getRuleName()));
        List<RuleInfo> ruleInfoAll = Lists.newArrayList(ruleInfoRepository.findAll(builder));
        List<RuleInfoTableResponse> responseList = ruleInfoAll.stream()
                .map(ruleInfo -> {
                    RuleInfoTableResponse response = new RuleInfoTableResponse();
                    ruleInfo.setFormulaInfos(null);
                    BeanUtils.copyProperties(ruleInfo, response);
                    return response;
                }).collect(Collectors.toList());
        return responseList;
    }
}
